package com.baitiaojun.moments.handler;

import com.baitiaojun.api.domain.user.RabbitMqDuplicate;
import com.baitiaojun.api.util.ConstantUtil;
import com.baitiaojun.moments.service.DuplicateService;
import lombok.Getter;
import lombok.NonNull;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;
import java.util.Objects;

/**
 * @类名 CallBackConfig
 * @描述 TODO
 * @作者 白条君
 * @创建日期 2022/11/27 16:03
 * @版本 1.0
 */
@Slf4j
@Getter
@Configuration
public class UserMomentsCallBackHandler implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {

    @Resource
    private RabbitTemplate rabbitTemplate;

    private boolean ack;

    @Resource
    private DuplicateService mqDuplicateService;

    @PostConstruct
    public void init() {
        rabbitTemplate.setConfirmCallback(this);
    }

    @SneakyThrows
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        long id = Long.parseLong(ObjectUtils.isNotEmpty(correlationData) ? Objects.requireNonNull(correlationData.getId()) : "");
        this.ack = ack;
        String status = mqDuplicateService.selectStatusById(id);
        if (!ack) {
            log.warn("消息发送到交换机失败，id是" + id + ", 原因是" + cause + "，等待定时器重新发送消息...");
            //发布失败的话，如果冗余信息的status是1就更新mysql冗余表中的status字段为0
            if (ConstantUtil.SUCCESS_STATUS.equals(status)) {
                mqDuplicateService.updateStatusById(RabbitMqDuplicate.builder().id(id)
                        .status(ConstantUtil.DEFAULT_STATUS)
                        .updatetime(new Date()).build()
                );
            }
        } else {
            //发成功的话，如果冗余信息的status是0就更新mysql冗余表中的status字段为1
            log.info("消息成功发布到交换机");
            if (ConstantUtil.DEFAULT_STATUS.equals(status)) {
                mqDuplicateService.updateStatusById(RabbitMqDuplicate.builder().id(id)
                        .status(ConstantUtil.SUCCESS_STATUS)
                        .updatetime(new Date()).build()
                );
            }
        }
    }

    @Override
    public void returnedMessage(Message message, int replyCode, @NonNull String replyText, @NonNull String exchange, @NonNull String routingKey) {
        log.warn("消息不可到达队列，将被投递到备份交换机处理，消息内容是{}，不可达路由是：{}，回退原因是：{}", new String(message.getBody()), routingKey, replyText);
    }
}